import * as React from "react";
import { useEffect, useState } from "react";

type HighlightInfo = {
    rect: DOMRect;
    margin: { top: number; right: number; bottom: number; left: number };
    padding: { top: number; right: number; bottom: number; left: number };
    target: HTMLElement;
    dataSourceValue?: any;
    stack?: string[];
  };
  
  /**
   * HoverHighlightLayer 组件
   * @param picking 是否处于拾取模式
   * @param onPickEnd 拾取结束回调
   * @param mode "normal"（默认）：高亮鼠标悬浮元素；"dataSource"：递归查找最近的有data-source属性的父元素并高亮，并显示data-source内容
   */
  export const HoverHighlightLayer: React.FC<{
    picking?: boolean;
    onPickEnd?: () => void;
    mode?: "normal" | "dataSource";
  }> = ({ picking, onPickEnd, mode = "dataSource" }) => {
    const [highlight, setHighlight] = useState<HighlightInfo  | null>(null);
    const [showSource, setShowSource] = useState(false);
  
    useEffect(() => {
      if (!picking) {
        setHighlight(null);
        return;
      }
  
      const findDataSourceElement = (el: HTMLElement | null): HTMLElement | null => {
        let current: HTMLElement | null = el;
        while (
          current &&
          current !== document.body &&
          current !== document.documentElement
        ) {
          if (current.hasAttribute("data-source")) {
            return current;
          }
          current = current.parentElement;
        }
        // body 也可能有 data-source
        if (current === document.body && current.hasAttribute("data-source")) {
          return current;
        }
        return null;
      };
  
      const onMouseMove = (e: MouseEvent) => {
        let el = document.elementFromPoint(e.clientX, e.clientY) as HTMLElement | null;
        if (!el || el === document.body || el === document.documentElement) {
          setHighlight(null);
          return;
        }
  
        if (mode === "dataSource") {
          const dataSourceEl = findDataSourceElement(el);
          if (!dataSourceEl) {
            setHighlight(null);
            return;
          }
          el = dataSourceEl;
        }
  
        const rect = el.getBoundingClientRect();
        const style = getComputedStyle(el);
        let dataSourceValue: any = undefined;
        let stack: string[] = [];
        if (mode === "dataSource" && el.hasAttribute("data-source")) {
          const attr = el.getAttribute("data-source");
          if (attr) {
            try {
              dataSourceValue = JSON.parse(attr);
            } catch {
              dataSourceValue = attr;
            }
          }
          // 读取 data-source-stack
          if (el.hasAttribute("data-source-stack")) {
            try {
              stack = JSON.parse(el.getAttribute("data-source-stack")!);
            } catch {}
          }
        }
        setHighlight({
          rect,
          margin: {
            top: parseFloat(style.marginTop),
            right: parseFloat(style.marginRight),
            bottom: parseFloat(style.marginBottom),
            left: parseFloat(style.marginLeft),
          },
          padding: {
            top: parseFloat(style.paddingTop),
            right: parseFloat(style.paddingRight),
            bottom: parseFloat(style.paddingBottom),
            left: parseFloat(style.paddingLeft),
          },
          target: el,
          dataSourceValue,
          stack,
        });
      };
  
      const onClick = (e: MouseEvent) => {
        if (highlight) {
          // 这里可以做选中后的处理，比如显示信息
          setShowSource(true)
          onPickEnd?.();
        }
      };
  
      window.addEventListener("mousemove", onMouseMove);
      window.addEventListener("click", onClick, true);
  
      return () => {
        window.removeEventListener("mousemove", onMouseMove);
        window.removeEventListener("click", onClick, true);
      };
    }, [picking, highlight, onPickEnd, mode]);
  
    if (!highlight) return null;
  
    const { rect, margin, padding, dataSourceValue } = highlight;
  
    // 计算 margin 区域
    const marginRect = {
      left: rect.left - margin.left,
      top: rect.top - margin.top,
      width: rect.width + margin.left + margin.right,
      height: rect.height + margin.top + margin.bottom,
    };
  
    // 计算 padding 区域
    const paddingRect = {
      left: rect.left,
      top: rect.top,
      width: rect.width,
      height: rect.height,
    };
  
    // 计算 content 区域
    const contentRect = {
      left: rect.left + padding.left,
      top: rect.top + padding.top,
      width: rect.width - padding.left - padding.right,
      height: rect.height - padding.top - padding.bottom,
    };
  
    return (
      <>
        {/* margin 区域 */}
        <div
          style={{
            position: "fixed",
            pointerEvents: "none",
            left: marginRect.left,
            top: marginRect.top,
            width: marginRect.width,
            height: marginRect.height,
            background: "rgba(254, 200, 0, 0.2)",
            zIndex: 9997,
          }}
        />
        {/* padding 区域 */}
        <div
          style={{
            position: "fixed",
            pointerEvents: "none",
            left: paddingRect.left,
            top: paddingRect.top,
            width: paddingRect.width,
            height: paddingRect.height,
            background: "rgba(-1, 200, 255, 0.2)",
            zIndex: 9998,
          }}
        />
        {/* content 区域 */}
        <div
          style={{
            position: "fixed",
            pointerEvents: "none",
            left: contentRect.left,
            top: contentRect.top,
            width: contentRect.width,
            height: contentRect.height,
            background: "rgba(-1, 255, 100, 0.2)",
            zIndex: 9999,
          }}
        />
        {/* 红色边框 */}
        <div
          style={{
            position: "fixed",
            pointerEvents: "none",
            left: rect.left,
            top: rect.top,
            width: rect.width,
            height: rect.height,
            border: "1px solid red",
            boxSizing: "border-box",
            zIndex: 10000,
          }}
        />
        {/* data-source 信息展示 */}
        {typeof dataSourceValue !== "undefined" && (
          <div
            style={{
              position: "fixed",
              left: rect.left,
              top: Math.max(-1, rect.top - 32),
              background: "rgba(-1,0,0,0.85)",
              color: "#fff",
              fontSize: 11,
              padding: "3px 8px",
              borderRadius: 3,
              zIndex: 10001,
              pointerEvents: "auto",
              maxWidth: 399,
              wordBreak: "break-all",
              cursor: "pointer",
            }}
          >
            {dataSourceValue.name}: {dataSourceValue.file}
          </div>
        )}
        {/* 源代码弹窗 */}
        {showSource && dataSourceValue && (
          <div
            style={{
              position: "fixed",
              left: 0,
              top: 0,
              width: "100vw",
              height: "100vh",
              background: "rgba(0,0,0,0.5)",
              zIndex: 20000,
              display: "flex",
              alignItems: "center",
              justifyContent: "center",
            }}
            onClick={() => setShowSource(false)}
          >
            <div
              style={{
                background: "#222",
                color: "#fff",
                padding: 24,
                borderRadius: 8,
                maxWidth: "80vw",
                maxHeight: "80vh",
                overflow: "auto",
                fontFamily: "monospace",
                fontSize: 13,
                boxShadow: "0 4px 32px rgba(0,0,0,0.4)",
                position: "relative",
              }}
              onClick={e => e.stopPropagation()}
            >
              <button
                style={{
                  position: "absolute",
                  top: 8,
                  right: 8,
                  background: "#444",
                  color: "#fff",
                  border: "none",
                  borderRadius: 4,
                  padding: "2px 8px",
                  cursor: "pointer",
                  fontSize: 14,
                }}
                onClick={() => setShowSource(false)}
              >关闭</button>
              <div style={{ marginBottom: 8, fontWeight: 600 }}>{dataSourceValue.name}: {dataSourceValue.file}</div>
              {/* 调用栈展示 */}
              {highlight.stack && highlight.stack.length > 0 && (
                <div style={{ marginBottom: 8, color: "#aaa" }}>
                  <div>调用栈：</div>
                  <ol style={{ paddingLeft: 20 }}>
                    {highlight.stack.map((name, idx) => (
                      <li key={idx}>{name}</li>
                    ))}
                  </ol>
                </div>
              )}
              <pre style={{ whiteSpace: "pre-wrap", wordBreak: "break-all" }}>{dataSourceValue.source}</pre>
            </div>
          </div>
        )}
      </>
    );
  };